package com.yantong.pay.yfz.pay;

import com.alibaba.fastjson.JSONObject;
import com.yantong.mapper.XLoginInfoMapper;
import com.yantong.pojo.*;
import com.yantong.constant.ProductType;
import com.yantong.exception.BDException;
import com.yantong.result.ResultVo;
import com.yantong.service.xcx.XCXLoginService;
import com.yantong.utils.ValidateUtil;
import com.yantong.pay.yfz.domain.pay.PaymentHelper;
import com.yantong.pay.yfz.domain.pay.domain.aliJSAPI.AliJSAPIRequest;
import com.yantong.pay.yfz.domain.pay.domain.aliJSAPI.AliJSAPIResponse;
import com.yantong.pay.yfz.domain.pay.domain.cashierPay.OrderGoods;
import com.yantong.pay.yfz.domain.pay.domain.cashierPay.OrderInfo;
import com.yantong.pay.yfz.domain.pay.domain.paymenQuery.PaymentQueryRequest;
import com.yantong.pay.yfz.domain.pay.domain.refund.RefundApplyRequest;
import com.yantong.pay.yfz.domain.pay.domain.refund.RefundApplyResponse;
import com.yantong.pay.yfz.domain.pay.domain.split.SplitInfo;
import com.yantong.pay.yfz.domain.pay.domain.split.SplitRequest;
import com.yantong.pay.yfz.domain.pay.domain.split.SplitResponse;
import com.yantong.pay.yfz.domain.pay.domain.wechatJSAPI.WechatJSAPIRequest;
import com.yantong.pay.yfz.domain.pay.domain.wechatJSAPI.WechatJSAPIResponse;
import com.yantong.pay.yfz.domain.pay.domain.wechatJSAPI.WxJsOrderGoods;
import com.yantong.pay.yfz.domain.pay.domain.wechatJSAPI.WxJsOrderInfo;
import com.yantong.pay.yfz.domain.pay.domain.withdraw.*;
import com.yantong.pay.yfz.util.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 易票联支付
 *
 * @author huangshuai-728982210@qq.com
 * @date 2021/3/1 16:06
 */
@Component
public class YFZPayutil {
	private static final Logger logger = LoggerFactory.getLogger(YFZPayutil.class);


	private static String customerCode2 = "562139003069032";
	@Value("${Applet.TemplatemsgCreateUserUrl}")
	private static String templatemsgCreateUserUrl = "";

	public ResultVo getPayConfig(Order order, double payPrice, Centre centre, List<OrderProduct> orderProductList, Member member, String attach, Integer payMethod, Boolean ytFlag, String notifyUrl, HttpServletRequest request, Member teamMember)
			throws Exception {
		DecimalFormat df = new DecimalFormat("###########0");
		String nowtime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
		String total_fee = df.format(payPrice * 100.0D);
		ResultVo resultVo = new ResultVo();
		resultVo.put("success", true);
		request.setCharacterEncoding("UTF-8");

		String outTradeNo = order.getOutTradeNo(); // 交易编号,商户侧唯一

		//付钱给商户
		String customerCode = centre.getYplCustomerCode();
		String yplPrivateKey = centre.getYplPrivateKey();
		String yplPrivateKeyPwd = centre.getYplPrivateKeyPwd();
		String yplPublicKey = centre.getYplPublicKey();
		String yplSignNo = centre.getYplSignNo();

		String appId = "";
		String openId = "";
		if (payMethod == 1) {
			appId = centre.getGzhAppid();
			openId = member.getOpenid();
		} else if (payMethod == 35) {
			appId = centre.getRelateAccount();
			openId = member.getAppOpenid();
		}
		String clientIp = "8.134.79.64"; // IP
		long payAmount = Long.valueOf(total_fee); // 支付金额,分为单位
		String payCurrency = "CNY"; // 币种，写死

		//String redirectUrl = ""; // 同步通知地址
		String attachData = attach; // 备注数据,可空
		String transactionStartTime = Config.getTransactionStartTime(); // 交易开始时间
		String transactionEndTime = ""; // 交易结束时间

		/* orderInfo参数对象填充 */
		List<WxJsOrderGoods> goodsList = new ArrayList<>();
		if (ValidateUtil.isNotEmptyCollection(orderProductList)) {
			for (OrderProduct orderProduct : orderProductList) {
				WxJsOrderGoods goods = new WxJsOrderGoods();
				goods.setName(orderProduct.getProductName());
				goods.setNumber(orderProduct.getTotal() + "");
				if (goodsList.size() == 1) {
					goods.setAmount(new BigDecimal(payPrice).longValue());
				} else {
					goods.setAmount(orderProduct.getPrice() == null ? 0L : orderProduct.getPrice().longValue());
				}
				goodsList.add(goods);
			}
		} else {
			WxJsOrderGoods goods = new WxJsOrderGoods();
			goods.setName(order.getRealname());
			goods.setNumber("1");
			goods.setAmount(new BigDecimal(payPrice).longValue());
			goodsList.add(goods);
		}
		WxJsOrderInfo orderInfo = new WxJsOrderInfo();
		orderInfo.setBusinessType("100006");
		if(null != order.getId()){
			orderInfo.setId(order.getId().toString());
		}
		orderInfo.setGoodsList(goodsList);

		WechatJSAPIRequest orderRequest = new WechatJSAPIRequest("3.0", payMethod, outTradeNo, customerCode, appId, openId, clientIp, orderInfo, payAmount,
				payCurrency, notifyUrl, attachData, transactionStartTime, transactionEndTime);
		if (null != order.getOrderType() && (ProductType.FreeCharge.getType() == order.getOrderType() || ProductType.Spellgroup.getType() == order.getOrderType())) {

			//isProcedureCustomer：
			//0 常规分账对象
			//1 收单手续费扣除对象
			//2 分账手续费扣除对象
			//3 收单和分账手续费扣除对象
			//splitInfoList.add(new SplitInfo(teamMember.getYplCustomerCode(), platformMoney.longValue(), 3));
			//使用延迟分账
			orderRequest.setNeedSplit(true);// 不填默认否，只有开通了分账业务的商户才可将该值设置为true
			//orderRequest.setSplitInfoList(splitInfoList);//不设置，使用延迟分账
			orderRequest.setSplitNotifyUrl("");// 非必填
			orderRequest.setSplitMain(centre.getYplCustomerCode()); //needSplit 为 true 时必填填作为分账主体商户的customerCode
			orderRequest.setSplitAttachData(UUID.randomUUID().toString().replaceAll("-", ""));// 非必填

			// 是否限制信用卡支付，不填默认是false(即不限制)
			orderRequest.setNoCreditCards(false);
			//}
		}
		String jsonData = JSONObject.toJSONString(orderRequest);
		logger.info("-------jsonData：" + jsonData);
		String sign = RsaUtils.sign(KeyUtil.getPrimaryKey(yplPrivateKey, yplPrivateKeyPwd), jsonData);//签名

		Map<String, String> header = new HashMap<String, String>();
		header.put("x-efps-sign", sign);
		header.put("x-efps-sign-no", yplSignNo);
		header.put("x-efps-sign-type", "SHA256withRSA");
		header.put("x-efps-timestamp", nowtime);
		header.put("Content-Type", "application/json");

		String url = Config.getWechatJSAPIUrl();
		logger.info("-------url：" + url);
		logger.info("-------易票联支付头部参数：" + JSONObject.toJSONString(header));
		logger.info("-------易票联支付参数：" + jsonData);
		WechatJSAPIResponse response = HttpUtil.post(url, jsonData, header, WechatJSAPIResponse.class, yplPublicKey);
		logger.info("易票联微信支付参数返回====" + JSONObject.toJSONString(response));
		resultVo.put("WechatH5Response", response);

		return resultVo;
	}

	/**
	 * 聚合支付（微信）
	 *
	 * @param order, payPrice, centre, orderProductList, member, attach, payMethod, ytFlag, notifyUrl
	 * @return com.jz.common.result.ResultVo
	 * @author huangshuai
	 * @date 2021/3/25 17:12
	 */
	public static ResultVo getjuhePayConfig(JuheOrder order, double payPrice, Centre centre, Centre ytCentre, List<OrderProduct> orderProductList, Member member, String attach, Integer payMethod, Boolean ytFlag, String notifyUrl, Member teamMember)
			throws Exception {
		DecimalFormat df = new DecimalFormat("###########0");
		String nowtime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
		//String sn = RandomStringUtils.randomAlphanumeric(32);
		String total_fee = df.format(payPrice * 100.0D);
		ResultVo resultVo = new ResultVo();
		resultVo.put("success", true);
		//request.setCharacterEncoding("UTF-8");

		String outTradeNo = order.getOutTradeNo(); // 交易编号,商户侧唯一

		//如果门店设置了易票联商户资料
		String customerCode = centre.getYplCustomerCode();
		; // 商户编号
		String yplPrivateKey = centre.getYplPrivateKey(); // 私钥
		String yplPrivateKeyPwd = centre.getYplPrivateKeyPwd(); //私钥密码
		String yplSignNo = centre.getYplSignNo(); //签名
		String yplPublicKey = centre.getYplPublicKey(); //公钥

		String appId = "";
		String openId = "";
		if (payMethod == 1) {
			appId = centre.getGzhAppid();
			openId = member.getOpenid();
		} else if (payMethod == 35) {
			appId = centre.getRelateAccount();
			openId = member.getAppOpenid();
		}
		String clientIp = "8.134.79.64"; // IP
		long payAmount = Long.valueOf(total_fee); // 支付金额,分为单位
		String payCurrency = "CNY"; // 币种，写死
		//String channelType = "01"; // 渠道类型，写死

		String redirectUrl = ""; // 同步通知地址
		String attachData = attach; // 备注数据,可空
		String transactionStartTime = Config.getTransactionStartTime(); // 交易开始时间
		String transactionEndTime = ""; // 交易结束时间

		/* orderInfo参数对象填充 */
		List<WxJsOrderGoods> goodsList = new ArrayList<>();
		for (OrderProduct orderProduct : orderProductList) {
			WxJsOrderGoods goods = new WxJsOrderGoods();
			goods.setName(orderProduct.getProductName());
			goods.setNumber(orderProduct.getTotal() + "");
			goods.setAmount(orderProduct.getPrice().longValue());
			goodsList.add(goods);
		}
		WxJsOrderInfo orderInfo = new WxJsOrderInfo();
		orderInfo.setBusinessType("100006");
		orderInfo.setId(order.getId().toString());
		orderInfo.setGoodsList(goodsList);

//		String type = "Wap";// wap网站URL地址
//		String wapURL = "=http://wx.globalcash.cn/new2/txs/cashier";// wap网站URL地址
//		String wapName = "收银台";// wap网站URL名称
//		WxH5SceneInfo sceneInfo = new WxH5SceneInfo(type, wapURL, wapName);

		WechatJSAPIRequest orderRequest = new WechatJSAPIRequest("3.0", payMethod, outTradeNo, customerCode, appId, openId, clientIp, orderInfo, payAmount,
				payCurrency, notifyUrl, attachData, transactionStartTime, transactionEndTime);

		// ----分账设置，注意分账金额总和等于交易金额-----
		//对账金额
		orderRequest.setNeedSplit(true);// 不填默认否，只有开通了分账业务的商户才可将该值设置为true
		//orderRequest.setSplitInfoList(splitInfoList);//不设置，使用延迟分账
		orderRequest.setSplitNotifyUrl("");// 非必填
		orderRequest.setSplitMain(centre.getYplCustomerCode()); //needSplit 为 true 时必填填作为分账主体商户的customerCode
		orderRequest.setSplitAttachData(UUID.randomUUID().toString().replaceAll("-", ""));// 非必填

		// 是否限制信用卡支付，不填默认是false(即不限制)
		orderRequest.setNoCreditCards(false);

		String jsonData = JSONObject.toJSONString(orderRequest);
		logger.info("-------jsonData：" + jsonData);
		String sign = RsaUtils.sign(KeyUtil.getPrimaryKey(yplPrivateKey, yplPrivateKeyPwd), jsonData);//签名

		Map<String, String> header = new HashMap<String, String>();
		header.put("x-efps-sign", sign);
		header.put("x-efps-sign-no", yplSignNo);
		//header.put("x-efps-sign-no","562539003602372001");
		header.put("x-efps-sign-type", "SHA256withRSA");
		header.put("x-efps-timestamp", nowtime);
		header.put("Content-Type", "application/json");

		String url = Config.getWechatJSAPIUrl();
		//String url = "http://efps.epaylinks.cn/api/txs/pay/WxJSAPIPayment";
		logger.info("-------url：" + url);
		WechatJSAPIResponse response = HttpUtil.post(url, jsonData, header, WechatJSAPIResponse.class, yplPublicKey);
		logger.info("易票联微信支付参数返回====" + JSONObject.toJSONString(response));
		resultVo.put("data", response);

		return resultVo;
	}

	/**
	 * 退款
	 *
	 * @return
	 * @throws Exception
	 */
	public static ResultVo refundApply(BigDecimal orderPayprice, String outTradeNo, Centre centre, String refundNo, String notifyUrl, String splitInfoListStr) throws Exception {
		DecimalFormat df = new DecimalFormat("###########0");
		String nowtime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

//		String total_fee = df.format(payPrice * 100.0D);
		orderPayprice = orderPayprice.multiply(new BigDecimal(100));
		ResultVo resultVo = new ResultVo();
		//request.setCharacterEncoding("UTF-8");

		String transactionNo = "";// 易票联订单号
		String customerCode = centre.getYplCustomerCode();// 琰通商户编号
		long amount = orderPayprice.longValue();// 原订单支付金额
		String sourceChannel = "API";// 渠道类型
		String outRefundNo = refundNo;// 商户退款单号
		long refundAmount = orderPayprice.longValue();// 申请退款金额
		String remark = "订单退款";// 退款申请说明
		List<SplitInfo> splitInfoList = JSONObject.parseArray(splitInfoListStr, SplitInfo.class);
		RefundApplyRequest refundRequest = new RefundApplyRequest(transactionNo, outTradeNo, customerCode, amount, notifyUrl,
				outRefundNo, refundAmount, remark, splitInfoList);

		final String jsonData = JSONObject.toJSONString(refundRequest);
		final String sign = RsaUtils.sign(KeyUtil.getPrimaryKey(centre.getYplPrivateKey(), centre.getYplPrivateKeyPwd()), jsonData);//签名

		Map<String, String> header = new HashMap<String, String>();
		header.put("x-efps-sign", sign);
		header.put("x-efps-sign-no", centre.getYplSignNo());
		header.put("x-efps-sign-type", "SHA256withRSA");
		header.put("x-efps-timestamp", nowtime);
		header.put("Content-Type", "application/json");
		String url = Config.getRefundApplyUrl();
		RefundApplyResponse response = HttpUtil.post(url, jsonData, header, RefundApplyResponse.class, centre.getYplPublicKey());
		System.out.println("交易结果：" + JSONObject.toJSONString(response));
		resultVo.put("data", response);
		return resultVo;
	}

	public static void main(String[] args) {
		BigDecimal splitMoney = BigDecimal.ZERO;
		BigDecimal pay_price = new BigDecimal(99.98).multiply(new BigDecimal(100));
		splitMoney = new BigDecimal(9.99).multiply(new BigDecimal(100)); //将对账金额转为分
		BigDecimal firstSplitPrice = pay_price.subtract(splitMoney);
		System.out.println(firstSplitPrice.longValue());
	}


	/**
	 * 单笔代付 商户单笔提现
	 *
	 * @return
	 * @throws Exception
	 */
	public static WithdrawToCardResponse withdrawalToCard(Map<String, String> map, String withdrawNotifyUrl, Withdrawals withdrawals) throws Exception {
		String nowtime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
		String outTradeNo = withdrawals.getApplyno(); // 交易编号,商户侧唯一
		// String customerCode = "";
		long payAmount = withdrawals.getDaMoney().multiply(new BigDecimal(100)).longValue();
		String payCurrency = "CNY";
		String notifyUrl = withdrawNotifyUrl;
		String remark = "";

		String yplPublicKey = RsaUtils.getPublicKey(Config.getPublicKeyFile(map.get("yplPublicKey")));
		String bankUserName = RsaUtils.encryptByPublicKey(withdrawals.getRealname(), yplPublicKey);
		String bankUserCert = RsaUtils.encryptByPublicKey(withdrawals.getIdcard(), yplPublicKey);
		String bankCardNo = RsaUtils.encryptByPublicKey(withdrawals.getBankcard(), yplPublicKey);

		WithdrawToCardRequest request = new WithdrawToCardRequest();
		request.setOutTradeNo(outTradeNo);
		request.setCustomerCode(Config.getCustomerCode());
		request.setAmount(payAmount);// 如果isFullAmount送1此值不送
		request.setIsAdvanceFund("");

		request.setBankUserName(bankUserName);
		request.setBankUserCert(bankUserCert);
		request.setBankCardNo(bankCardNo);
		// request.setBankNo("102xxx0012");//联行号
		request.setBankName(withdrawals.getBankname());
		request.setBankProvince("");
		request.setBankCity("");
		request.setBankSub("");
		request.setBankAccountType("2");// 1：对公，2：对私
		request.setPayCurrency(payCurrency);
		request.setNotifyUrl(notifyUrl);
		request.setRemark(remark);
		request.setCustomerCode(map.get("yplCustomerCode"));
		request.setIsFullAmount(0);// isFullAmount 是否全额代付 Integer 否 0：非全额代付，默认值;
		// 1：全额代付 ;
		// amount有值时，isFullAmount参数不做检查，amount无值时，isFullAmount必需=1，否则报文错误
		request.setNonceStr(UUID.randomUUID().toString().replaceAll("-", ""));

		final String sign = RsaUtils.sign(KeyUtil.getPrimaryKey(map.get("yplPrivateKey"), map.get("yplPrivateKeyPwd")), JSONObject.toJSONString(request));//签名
		Map<String, String> header = new HashMap<String, String>();
		header.put("x-efps-sign", sign);
		header.put("x-efps-sign-no", map.get("yplSignNo"));
		header.put("x-efps-sign-type", "SHA256withRSA");
		header.put("x-efps-timestamp", nowtime);
		header.put("Content-Type", "application/json");
		String url = Config.getWithdrawalToCardUrl();
		logger.info("交易参数：" + JSONObject.toJSONString(request));
		WithdrawToCardResponse response = HttpUtil.post(url, JSONObject.toJSONString(request), header, WithdrawToCardResponse.class, map.get("yplPublicKey"));

		logger.info("交易结果：" + JSONObject.toJSONString(response));

		return response;
	}

	/**
	 * 商户余额查询
	 *
	 * @return
	 * @throws Exception
	 */
	public static CustomerAccountQueryResp accountQuery(Centre centre, String customerCode) throws Exception {
		String nowtime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

		Map<String, String> request = new HashMap<String, String>();
		request.put("customerCode", customerCode);
		request.put("nonceStr", UUID.randomUUID().toString().replaceAll("-", ""));

		final String sign = RsaUtils.sign(KeyUtil.getPrimaryKey(centre.getYplPrivateKey(), centre.getYplPrivateKeyPwd()), JSONObject.toJSONString(request));//签名
		Map<String, String> header = new HashMap<String, String>();
		header.put("x-efps-sign", sign);
		header.put("x-efps-sign-no", centre.getYplSignNo());
		header.put("x-efps-sign-type", "SHA256withRSA");
		header.put("x-efps-timestamp", nowtime);
		header.put("Content-Type", "application/json");
		String url = Config.getAccountQueryUrl();
		CustomerAccountQueryResp response = HttpUtil.post(url, JSONObject.toJSONString(request), header, CustomerAccountQueryResp.class, centre.getYplPublicKey());
		System.out.println("交易结果：" + JSONObject.toJSONString(response));
		return response;
	}

	/**
	 * 延迟分账(分账的到账会有一点延迟，得等支付交易金额入账后才按照分账业务的结算周期入到分账商户中)
	 */
	public static SplitResponse split(Centre centre, SplitRequest request) throws Exception {
		return RemoteInvoker.invoke(request, Config.getSplitPayUrl(), centre.getYplPrivateKey(), centre.getYplPrivateKeyPwd(), centre.getYplSignNo(), centre.getYplPublicKey(), SplitResponse.class);
	}

	/**
	 * 分账子商户提现（最小提现金额1.1元，也就是必须大于1块钱）
	 *
	 * @param customerCode2 子商户
	 */
	public static Withdraw4SubMerchantResponse WithdrawalForSubMerchant(Centre centre, String notifyUrl, String customerCode2, String remark, String outTradeNo, BigDecimal payAmount) throws Exception {
		String version = "3.0";
		long payAmount2 = payAmount.multiply(new BigDecimal("100")).longValue();
		String payCurrency = "CNY";
		String nonceStr = UUID.randomUUID().toString().replaceAll("-", "");

		Withdraw4SubMerchantRequest request = new Withdraw4SubMerchantRequest(version, centre.getYplCustomerCode(), outTradeNo,
				customerCode2, null, payAmount2, payCurrency, notifyUrl, remark, nonceStr);

		Withdraw4SubMerchantResponse response = PaymentHelper.withdraw4SubMerchant(request, centre.getYplPrivateKey(), centre.getYplPrivateKeyPwd(), centre.getYplSignNo(), centre.getYplPublicKey());
		System.out.println("交易结果：" + JSONObject.toJSONString(response));

		return response;
	}

}
